#include <iostream>
#include <vector>

void f(int, int) {
}

template<typename T, 
	template<typename Elem, typename Alloc>
	typename Container, 
		typename Index>
T& authAndAccess(Container<T, std::allocator<T>>& container, Index index) {
	return container[index];
}

template<typename Container, typename Index>
auto authAndAccess1(Container& container, Index i) 
-> decltype(container[i])
{
	return container[i];
}

template<typename Container, typename Index>
auto authAndAccess2(Container& container, Index i)
{
	return container[i];
}

template<typename Container, typename Index>
decltype(auto) authAndAccess3(Container& container, Index i)
{
	return container[i];
}

struct TestStr {
	int a;

	TestStr& operator=(int oa) {
		std::cout << "TestStr& operator=(int oa)" << std::endl;
		a = oa;
		return *this;
	}
};


template<typename Container, typename Index>
decltype(auto) authAndAccess4(Container&& container, Index i)
{
	container[i]++;
	return container[i];
	//return std::forward<Container>(container)[i];
}



int main() {
	/*int a = 10;
	const int& rca = 10;
	const int&& rrca = 10;
	const int* const cpca = &a;

	decltype(a) b;
	decltype(rca) rcb = 100;
	decltype(rrca) rrcb = 100;
	decltype(cpca) cpcb = &b;

	
	int aa[5] = { 0, 1, 2, 3, 4 };

	decltype(aa) ab = { 1, 2, 3, 4, 5 };

	decltype(f) f1;*/

	/*int a = 10;
	const int ca = 10;
	int* pa = &a;

	decltype((a)) ra = a;
	decltype((ca)) cra = ca;

	decltype(pa) pb = &a;
	decltype(*pa) rb = a;


	decltype(10) ra;*/

	std::vector<int> vec = { 1, 2, 3, 4, 5 };
	int& r = authAndAccess(vec, 0);
	std::cout << r << std::endl;

	r = authAndAccess1(vec, 1);
	std::cout << r << std::endl;

	//authAndAccess2(vec, 2) = 1;

	authAndAccess3(vec, 3) = 3;
	r = authAndAccess3(vec, 3);
	std::cout << r << std::endl;

	std::vector<bool> vecb = { true, false, true };
	authAndAccess2(vecb, 1) = true;
	std::cout << vecb[1] << std::endl;

	std::vector<TestStr> vect = { {1}, {2}, {3} };
	authAndAccess2(vect, 1) = 0;
	std::cout << vect[1].a << std::endl;

	r = authAndAccess4(vec, 4);
	std::cout << r << std::endl;

	r = authAndAccess4(std::vector<int>({ 1, 2, 3, 4, 5 }), 0);
	std::cout << r << std::endl;


	std::vector<int>&& v = std::vector<int>({ 1, 2, 3, 4, 5 });
	decltype(auto) ve = v[1];

	int (&&ra)[5] = { 0, 1, 2, 3, 4 };
	decltype(auto) rae = v[1];

	return 0;
}